#include <sstream>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/foreach.hpp>
#include "DatabaseTable.h"
#include "DatabaseTableError.h"

#define foreach BOOST_FOREACH

using namespace kc_sf;

// ------------------------------------------------------ //

DatabaseTable::DatabaseTable( const DatabaseRecord &column_names )
: t_column_names( column_names )
{
	if( t_column_names.empty() )
		throw DatabaseTableError( "Stworzono tabelkę, która nie posiada kolumn! " );
}

// ------------------------------------------------------ //

void DatabaseTable::insert( const DatabaseRecord &record )
{
	if( record.size() != t_column_names.size() )
	{
		std::stringstream err_stream;
		err_stream << "Błąd przy mapowaniu danych z bazy danych na tabelkę "
			<< ".\nNie zgadza się liczba kolumn w rekordzie. Powinno być "
			<< t_column_names.size() << ", a jest " << record.size();

		throw DatabaseTableError( err_stream.str() );
	}

	t_values.push_back( record );
}

// ------------------------------------------------------ //

DatabaseColumn DatabaseTable::selectColumn(
	const std::string &column_name ) const
{
	size_t column_index = -1;
	for( size_t i = 0; i < t_column_names.size(); ++i )
	{
		if( boost::iequals( column_name, t_column_names [i] ) )
		{
			column_index = i;
			break;
		}
	}

	if( column_index == size_t( -1 ) )
	{
		throw DatabaseTableError(
			"Błąd pobierania danych z tabeli. W tabeli nie ma kolumny " + column_name );
	}

	DatabaseColumn column;
	foreach( DatabaseRecord trecord, t_values )
	{
		column.push_back( trecord[ column_index ] );
	}

	return column;
}

// ------------------------------------------------------ //

const DatabaseRecords & DatabaseTable::selectAll() const
{
	return t_values;
}

// ------------------------------------------------------ //

DatabaseRecords DatabaseTable::select(
	const std::vector <std::string> &column_names ) const
{
	std::vector <size_t> column_indexes;

	for( size_t i = 0; i < t_column_names.size(); ++i )
	{
		foreach( std::string column_name, column_names )
		{
			if( boost::iequals( column_name, t_column_names [i] ) )
			{
				column_indexes.push_back( i );
				break;
			}
		}
	}

	if( column_indexes.size() != column_names.size() )
	{
		throw DatabaseTableError(
			"Błąd pobierania danych z tabeli. W tabeli nie ma którejś z wymienionych kolumn ");
	}

	std::vector <DatabaseRecord > selected_values;
	foreach( DatabaseRecord trecord, t_values )
	{
		DatabaseRecord selected_record;
		foreach( size_t index, column_indexes )
		{
			selected_record.push_back( trecord[ index ] );
		}
		selected_values.push_back( selected_record );
	}

	return selected_values;
}

// ------------------------------------------------------ //

const DatabaseRecord & DatabaseTable::getColumnNames() const
{
	return t_column_names;
}

// ------------------------------------------------------ //

DatabaseRecord & DatabaseTable::getRecord( size_t record_index )
{
	if( record_index >= recordsNr () )
		throw DatabaseTableError( "Indeks rekordu większy niż ilość rekordów w tabelce! " );

	return t_values[ record_index ];
}

// ------------------------------------------------------ //

const DatabaseRecord & DatabaseTable::getRecord( size_t record_index ) const
{
	if( record_index >= recordsNr () )
		throw DatabaseTableError( "Indeks rekordu większy niż ilość rekordów w tabelce! " );

	return t_values[ record_index ];
}

// ------------------------------------------------------ //

size_t DatabaseTable::recordsNr () const
{
	return t_values.size();
}
